﻿#include "mslog.h"

//初始化
int msl_init(msl_t *log, const char *filename) {
	int ret = 0;
	int i = 0;
	if (log != NULL) {
		log->starttime = msl_get_time();
		log->timefmt = MSL_TIME_ELAPSED; //默认为启动时间
		log->outfd = stdout; //标准输出
		log->loglevel = MSL_VERBOSE; //默认为打开全部输出
		for (i = 0; i < MSL_COUNT; ++i) {
			log->fmt_set[i] = MSL_FMT_NORMAL; //默认显示日志级别和时间
		}
		msl_set_logout(log, filename);

	} else {
		ret = -1;
	}
	return ret;
}
//销毁日志 这里主要是关闭文件描述符
int msl_release(msl_t *log) {
	int ret = 0;
	if (log != NULL) {
		if (log->outfd != NULL && log->outfd != stdout && log->outfd != stderr
				&& log->outfd != stdin) {
			fflush(log->outfd);
			return fclose(log->outfd);
		} else {
			ret = -1;
		}
	} else {
		ret = -1;
	}
	return ret;
}

//设置日志输出
int msl_set_logout(msl_t *log, const char *filename) {
	int ret = 0;
	FILE *fd = NULL;

	if (log != NULL) {
		if (filename != NULL) {
			fd = fopen(filename, "a+");
			if (fd == NULL) {
				log->outfd = stdout;
				//TODO 输出错误信息
				fprintf(stderr, "errno = [%d][%s]\n", errno, strerror(errno));
			} else {
				log->outfd = fd;
			}
		} else {
			log->outfd = stdout;
		}
	} else {
		ret = -1;
	}
	return ret;
}
//设置日志级别 低于当前日志级别的不打印信息
int msl_set_level(msl_t *log, int level) {
	int ret = -1;

	if (log != NULL) {
		if (level >= MSL_NOMSG && level <= MSL_VERBOSE) {
			ret = 0;
			log->loglevel = level;
		}
	}
	return ret;
}

//根据日志级别设置输出内容
int msl_set_fmt(msl_t *log, int level, size_t set) {
	int ret = -1;

	if (log != NULL) {
		if (level >= MSL_NOMSG && level <= MSL_VERBOSE) {
			ret = 0;
			log->fmt_set[level] = set;
		}
	}
	return ret;
}

//设置时间戳格式  true(0000001.180) false(19700101|08:00:22.372)
int msl_set_timefmt(msl_t *log, MSL_TIME_FMT fmt) {
	int ret = -1;

	if (log != NULL) {
		log->timefmt = fmt;
	}
	return ret;
}

//获取当前时间字符串
int msl_get_datetime(char *dtime, int len) {
	struct timeb tz;
	struct tm *p = NULL;
	if (dtime == NULL || len < MSL_DTIME_LEN) {
		return -1;
	}
	//memset(dtime, 0x00, len);
	ftime(&tz);
	p = localtime(&(tz.time));
	sprintf(dtime, "%02d%02d%02d|%02d:%02d:%02d.%03d", 1900 + p->tm_year,
			1 + p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec,
			tz.millitm);
	return 0;
}

//获取系统启动时间
unsigned int msl_get_time() {
	unsigned int timeMs = 0;
	struct timespec timeCurrent;

	clock_gettime(CLOCK_MONOTONIC, &timeCurrent);
	timeMs = timeCurrent.tv_sec * 1000U;
	timeMs += timeCurrent.tv_nsec / 1000000U;
	return timeMs;
}

//日志输出
bool msl_output(msl_t *log, int level, const char *file, const char *func,
		const long line) {
	bool ret = false;
	if (log != NULL) {
		if (level >= MSL_NOMSG && level <= MSL_VERBOSE
				&& log->loglevel >= level) {
			fprintf(log->outfd, "@%s|", MSGHEAD);

			/* package level info */
			if (log->fmt_set[level] & MSL_FMT_LVL) {
				static const char *level_output_info[] = { "N", "A", "E", "W",
						"I", "D", "V", "U" };
				fprintf(log->outfd, "%s|", level_output_info[level]);
			}

			/* package process info */
			if (log->fmt_set[level] & MSL_FMT_P_INFO) {
				fprintf(log->outfd, "pid:%d|", getpid());
			}

			/* package thread info */
			if (log->fmt_set[level] & MSL_FMT_T_INFO) {
				fprintf(log->outfd, "tid:%d|", gettid());
			}

			/* package time info */
			if (log->fmt_set[level] & MSL_FMT_TIME) {
				char dtime[2 * MSL_DTIME_LEN + 2];
				memset(dtime, 0x00, sizeof(dtime));

				if (log->timefmt == MSL_TIME_ALL) {
					msl_get_datetime(dtime, MSL_DTIME_LEN);

					unsigned int elapsedtime = msl_get_time() - log->starttime;
					snprintf(dtime + strlen(dtime), MSL_DTIME_LEN, "|%07d.%03d",
							elapsedtime / 1000, elapsedtime % 1000);
				} else if (log->timefmt == MSL_TIME_DETAL) {
					msl_get_datetime(dtime, MSL_DTIME_LEN);
				} else { //MSL_TIME_ELAPSED
					unsigned int elapsedtime = msl_get_time() - log->starttime;
					snprintf(dtime, MSL_DTIME_LEN, "%07d.%03d",
							elapsedtime / 1000, elapsedtime % 1000);
				}

				fprintf(log->outfd, "%s|", dtime);
			}

			/* package file info */
			if (log->fmt_set[level] & MSL_FMT_FILE) {
				if (file != NULL) {
					fprintf(log->outfd, "%s:", file);
				}
			}

			/* package func info */
			if (log->fmt_set[level] & MSL_FMT_FUNC) {
				if (func != NULL) {
					fprintf(log->outfd, "(func:%s):", func);
				}
			}

			/* package line num info */
			if (log->fmt_set[level] & MSL_FMT_LINE) {
				fprintf(log->outfd, "(line:%ld) ", line);
			}
			ret = true;
		}
	}

	return ret;
}
//打印16进制数据 格式如下
//Displacement -1--2--3--4--5--6--7--8-Hex-0--1--2--3--4--5--6  --ASCII Value--
//00000(00000) 30 7f 04 08 00 00 00 00 00 d0 08 01 b1 8d 04 08  0*******Ð**±**
//00016(00010) 28 af 04 08 64 8a 04 08 ec 48 07 01 c6 2a fc cd  (¯**d**ìH**Æ*üÍ
void memdump(FILE* fd, unsigned char *addr, long len) {

	if (fd != NULL) {
		int i = 0, lineno = 0, n = 0, count = 0, total_lines = 0, page_length =
				0;
		char *ptr = NULL;
		char line[MSL_DUMP_LINE_MAX_SIZE] = { 0 },
				page[MSL_DUMP_PAGE_MAX_SIZE] = { 0 };
		unsigned char var[2] = { 0, 31 };
		const unsigned char *dump = NULL;

		dump = addr;
		total_lines = (len - 1) / MSL_DUMP_COL_NUM;

		while (dump < (addr + len)) {
			for (lineno = 0; lineno <= total_lines; lineno++) {
				ptr = line;
				memset(line, 0, sizeof(line));
				count = lineno * MSL_DUMP_COL_NUM;
				sprintf(ptr, "%05d", count);
				ptr += 5;
				sprintf(ptr, "(%05x) ", count);
				ptr += 8;
				for (i = 0; (i < MSL_DUMP_COL_NUM)&& (dump < (addr + len)); i++){
				sprintf(ptr, "%02x ", *dump);
				ptr += 3;
				dump += 1;
			}
				for (n = 0; n < MSL_DUMP_COL_NUM - i; n++) {
					sprintf(ptr, "   ");
					ptr += 3;
				}
				sprintf(ptr, " ");
				ptr += 1;
				dump = dump - i;
				for (n = 0; n < i; n++) {
					if (*dump <= var[1] && *dump >= var[0]) {
						sprintf(ptr, "*");
						ptr += 1;
					} else {
						sprintf(ptr, "%c", *dump);
						ptr += 1;
					}
					dump += 1;
				}
				strcat(page, line);
				strcat(page, "\n");
				page_length += (ptr - line + 1);

				if (0 == (lineno + 1) % MSL_DUMP_PAGE_MAX_LINE) {
					fwrite(MSL_DUMP_HEAD_STR, strlen(MSL_DUMP_HEAD_STR), 1, fd);
					fwrite(page, page_length, 1, fd);
					memset(page, 0, sizeof(page));
					page_length = 0;
				}
			} /* end of for    */
		} /* end of while    */
		fwrite(MSL_DUMP_HEAD_STR, strlen(MSL_DUMP_HEAD_STR), 1, fd);
		fwrite(page, page_length, 1, fd);
	}
}
